<script setup>
import _ from 'lodash'
import BuilderVarsCreate from './builder-vars-create.vue';
import {computed, onMounted, reactive, toRefs, watch} from "vue";
import {$WinMicrosvc} from "@jzl/comps-mg";
import {api} from "@jzl/api";
import {DFT_ICONS} from "@jzl/icons";
import { VueDraggableNext } from 'vue-draggable-next'

let DFT = {
  prop: "",
  type: "string",
  default: null,
  force: false,       // 是否默认不可删除
  initType: "static",
  iTypes: [],    // 支持的类型[ 'static', 'api' ]
  initPath: "",
  varName: "",    // page var name
  emptyDefault: true,
  api: null,
  mbCode: null,
  formCode: null,
  viewCode: null,
  itemName: null,
  reportId: null,
  reportCode: null,
  apiFilter: {},
  mapiFilter: {}
};

defineOptions({
  name: 'BuilderVars'
})

const modelValue = defineModel([])

const emit = defineEmits(['change'])
const props = defineProps({
  label: "变量列表",
  dialog: false,
  isItem: false,
  item: null,
  triggerPageType: "page"
})

const {
  vars,
  action,
  form,
  apiMap,
  mbMap,
  optionMap,
  mbList,
  mbProps,
  json,
  varFormWinShow
} = toRefs(reactive({
  vars: [
    /*{ prop: "x", type: "String", default: null, initType: "api", initPath: "", emptyDefault: true, api: null, mbCode: null, formCode: null, itemName: null },*/
  ],
  action: 'view',
  form: _.cloneDeep(DFT),

  apiMap: {},
  mbMap: {},
  optionMap: {},
  mbList: [],
  mbProps: {
    label: 'name',
    value: 'code',
    children: 'subs'
  },
  json: null,
  varFormWinShow: false
}))

/*const actionName = computed(() => {
  if (action.value === 'update') {
    return "修改变量"
  } else if (action.value === 'create') {
    return "创建变量"
  } else {
    return "查看变量"
  }
})*/

const isView = computed(() => {
  return action.value === 'view';
})

const isUpdate = computed(() => {
  return action.value === 'update';
})

watch(() => modelValue.value, (newVal, oldVal) => {
  willReceiveProps(newVal);
}, {deep: true})

watch(() => vars.value, (newVal, oldVal) => {
  modelValue.value = newVal
}, {deep: true})

onMounted(() => {
  vars.value = _.cloneDeep(modelValue.value);
  loadMbTree();
})

const willReceiveProps = (newVal) => {
  if (!$utils.deepEquals(newVal, vars.value)) {
    if (newVal) {
      vars.value = _.cloneDeep(newVal);
    } else {
      vars.value = [];
    }
  }
}

const getVarTypeIcon = (type) => {
  let icon = "";

  if (type === 'mapi') {
    icon = DFT_ICONS.api; // /"fa-paper-plane mapi";
  } else if (type === 'api') {
    icon = DFT_ICONS.database; // "fa-database api";
  } else if (type === 'mb') {
    icon = DFT_ICONS.mb; // "fa-maxcdn mb";
  } else if (type === 'query') {
    icon = DFT_ICONS.varQuery; // "fa-check-square1 option";
  } else if (type === 'iQuery') {
    icon = DFT_ICONS.varQuery; // "fa-seedling query";
  } else if (type === 'var') {
    icon = DFT_ICONS.exchange
  } else {
    icon = DFT_ICONS.varConst
  }

  return icon;
}

const getTypeTag = (type) => {
  return {
    'string': 'S',
    'number': 'N',
    'json': 'J',
    'table': 'T',
  }[type]
}

const loadMbTree = async () => {
  let data = await api.mb.getMbTree();
  mbList.value = data || [];
}

const initExt = async (v) => {
  if (v.initType === 'mapi') {

  } else if (v.initType === 'api') {
    let formCode = _.get(v, "formCode");
    let viewCode = _.get(v, "viewCode");
    let fullForm = await api.form.getFormByCode(formCode, viewCode);

    let key = `${formCode}${viewCode ? ('$' + viewCode) : ''}`;
    // this.$set(apiMap.value, key, fullForm);
    apiMap.value[key] = fullForm;
  } /*else if(v.initType === 'option') {
  } */
  else if (v.initType === 'mb') {
    let mbCode = _.get(v, "mbCode");
    let mbInfo = await api.mb.getMbByCode(mbCode);
    let key = mbCode;
    // this.$set(mbMap.value, key, mbInfo);
    mbMap.value[key] = mbInfo;
  }
}

const handleSelectVar = (v) => {
  let iForm = _.cloneDeep(v);

  if (iForm && _.isString(iForm.defaultJson)) {
    try {
      iForm.defaultJson = JSON.parse(iForm.defaultJson)
    } catch (e) {
    }
  }

  form.value = iForm;
  action.value = 'view';
  initExt(v);
  if (props.dialog) {
    handleShowUpdate();
  }
}

const handleShowCreate = () => {
  form.value = _.cloneDeep(DFT);
  action.value = 'create';

  if (props.dialog) varFormWinShow.value = true;
}

const handleShowUpdate = () => {
  action.value = 'update';
  if (props.dialog) varFormWinShow.value = true;
}

const handleSave = () => {
  if (!form.value.prop) {
    $jui.toast("属性名不能为空！");
    return;
  }

  if (form.value.type === 'json' && _.isString(form.value.defaultJson)) {
    try {
      let json = JSON.parse(form.value.defaultJson);
      if (json) form.value.defaultJson = json;
    } catch (e) {
      $jui.toast("JSON 默认值格式不正确！");
      return;
    }
  }
  if (action.value === 'create') {
    if (!vars.value) vars.value = [];
    vars.value.push(form.value);
  } else if (action.value === 'update') {
    let updateVar = _.find(vars.value, {prop: form.value.prop});
    _.assign(updateVar, form.value);
  }

  handleSelectVar(form.value);

  modelValue.value = vars.value
  varFormWinShow.value = false;

  emit("change", vars.value);
}

const handleCancel = () => {
  action.value = 'view';
  varFormWinShow.value = false;
}

const handleShowRemove = (v, idx) => {
  if (!v?.prop) return;

  $jui.confirm(`确定删除变量【${v.prop}】！`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    vars.value.splice(idx, 1);
    if (form.value && v.prop === form.value.prop) {
      if (!props.dialog) handleSelectVar(_.get(vars.value, '[0]', {}));
    }
  }).catch(() => {
  });
}

const handleBeforeClose = () => {
  handleCancel();
}

const handleVarStateRefresh = (v) => {
  let modelName = _.get(v, "prop");
  let pageItemCode = _.get(props.item, "page_item_code");
  // console.log(`itemStateRefresh:${ pageItemCode }, ${ modelName }`, this.item)
  $bus.emit(`itemStateRefresh:${pageItemCode}`, modelName);
}
</script>

<template>
  <div class="wd-vars" :class="{ 'wd-vars-dialog': dialog }">
    <div class="wd-vars-list">
      <div class="wd-vars-header">
        <span class="flex-1">{{ label || "变量列表" }}</span>
        <span class="xbtn" @click="handleShowCreate">
          <JIcon :icon="DFT_ICONS.add" /> 新增</span>
      </div>
      <VueDraggableNext v-model="vars">
        <template v-for="(v, idx) in vars" :key="v">
          <div
            v-if="v"
            class="wd-vars-item"
            :class="{ 'active': v?.prop === form?.prop && !dialog }"
            @click="handleSelectVar(v)"
          >
            <!--<div class="action-index fa fa-speakap"></div>-->
            <!--<div class="action-index fa fa-minus-square"></div>
            <div class="action-index fa fa-creative-commons-nd"></div>-->
            <JIcon
              :icon="getVarTypeIcon(v.initType)"
              class="wd-vars-item-icon"
              :class="getVarTypeIcon(v.initType)"
            />
            <div class="wd-vars-item-text" v-tippy :content="v.prop + (v.label ? `<br/>${ v.label }`: '')">
              <div class="wd-vars-item-prop" v-text="v.prop"></div>
              <div class="wd-vars-item-label" v-text="v.label"></div>
            </div>
            <div
              class="wd-vars-item-remark"
              v-tippy :content="v.type"
            >{{ getTypeTag(v.type) }}</div>
            <JIcon
              :icon="DFT_ICONS.refresh"
              class="wd-vars-item-refresh"
              @click.stop="handleVarStateRefresh(v)"
            />
            <JIcon
              v-if="v.force"
              :icon="DFT_ICONS.lock"
              class="wd-vars-item-remove"
              v-tippy content="锁定"
            />
            <JIcon
              v-else
              :icon="DFT_ICONS.delete"
              class="wd-vars-item-remove"
              @click.stop="handleShowRemove(v, idx)"
              v-tippy content="删除"
            />
          </div>
        </template>
        <div class="wd-vars-item active" v-if="action === 'create'">
          <JIcon
            :icon="getVarTypeIcon(form.initType)"
            class="wd-vars-item-icon"
            :class="getVarTypeIcon(form.initType)"
          />
          <div class="wd-vars-item-prop">新增变量</div>
          <JIcon
            :icon="DFT_ICONS.delete"
            class="wd-vars-item-remove"
            @click.stop="handleCancel()"
          />
        </div>
      </VueDraggableNext>
    </div>
    <BuilderVarsCreate
      v-if="!dialog"
      :action="action"
      :form="form"
      :api-map="apiMap"
      :mb-map="mbMap"
      :mb-list="mbList"
      v-bind="$attrs"
      @save="handleSave"
      @cancel="handleCancel"
      @showCreate="handleShowCreate"
      @showUpdate="handleShowUpdate"
    />

    <el-dialog
      v-if="dialog"
      title="变量维护"
      v-model="varFormWinShow"
      :close-on-click-modal="false"
      width="900px"
      :append-to-body="true"
      custom-class="m-dialog-style"
      :before-close="handleBeforeClose"
    >
      <BuilderVarsCreate
        v-if="dialog"
        :action="action"
        :form="form"
        :api-map="apiMap"
        :mb-map="mbMap"
        :mb-list="mbList"
        :dialog="true"
        :is-item="isItem"
        :trigger-page-type="triggerPageType"
        v-bind="$attrs"
        @save="handleSave"
        @cancel="handleCancel"
        @showCreate="handleShowCreate"
        @showUpdate="handleShowUpdate"
      />
    </el-dialog>
  </div>
</template>
